/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package wat.ziszcommon.transport;

import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

/**
 *
 * @author Krzysiek
 */
public class EprOpenSslContextFactory {

    private static EprOpenSslContextFactory serverFactoryInstance;
    private static EprOpenSslContextFactory clientFactoryInstance;
    private static SSLContext serverInstance = null;
    private static SSLContext clientInstance = null;
    private static final String PROTOCOL = "TLS";
    private String KEY_MANAGER_FACTORY_ALGORITHM;
    private boolean isServer;
    private InputStream certFile = null;
    private String certPassword = null;

    private EprOpenSslContextFactory(boolean server) {
        this.isServer = server;
        String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
        if (algorithm == null) {
            algorithm = KeyManagerFactory.getDefaultAlgorithm();
        }

        KEY_MANAGER_FACTORY_ALGORITHM = algorithm;
    }

    public static EprOpenSslContextFactory getInstance(boolean server) {
        if (server) {
            if (serverFactoryInstance == null) {
                serverFactoryInstance = new EprOpenSslContextFactory(server);
            }
            return serverFactoryInstance;
        } else {
            if (clientFactoryInstance == null) {
                clientFactoryInstance = new EprOpenSslContextFactory(server);
            }
            return clientFactoryInstance;
        }
    }

    public SSLContext getSSLContext() throws GeneralSecurityException, IOException {
        if (isServer) {
            if (serverInstance == null) {
                serverInstance = createServerSSLContext();
            }
            return serverInstance;
        } else {
            if (clientInstance == null) {
                clientInstance = createClientSSLContext();
            }
            return clientInstance;
        }
    }

    //keytool -genkey -alias erpopen -keysize 512 -validity 3650 -keyalg RSA -dname "CN=wcy.wat.edu.pl, OU=XXX CA, O=WCY, L=Warszawa, S=Warszawa, C=SE" -keypass erpopenpw -storepass erpopenpw -keystore erpopen.cert
    public void setCertFile(InputStream certFile) {
        this.certFile = certFile;
    }

    public void setCertPassword(String certPassword) {
        this.certPassword = certPassword;
    }

    private SSLContext createServerSSLContext() throws GeneralSecurityException, IOException {
        char[] certPasswordChars = null;
        KeyStore ks = KeyStore.getInstance("JKS");
        InputStream in = certFile;
        try {
            certPasswordChars = certPassword.toCharArray();
            ks.load(in, certPasswordChars);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ignored) {
                }
            }
        }

        // Set up key manager factory to use our key store
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM);
        kmf.init(ks, certPasswordChars);

        // Initialize the SSLContext to work with our key managers.
        SSLContext sslContext = SSLContext.getInstance(PROTOCOL);
        sslContext.init(kmf.getKeyManagers(),
                ErpOpenTrustManagerFactory.X509_MANAGERS, null);

        return sslContext;
    }

    private SSLContext createClientSSLContext() throws GeneralSecurityException {
        SSLContext context = SSLContext.getInstance(PROTOCOL);
        context.init(null, ErpOpenTrustManagerFactory.X509_MANAGERS, null);
        return context;
    }
}
